/*
 * Copyright (C) 2012  Romain DUBOIS
 * 
 * This file is part of NeMoS - Network and Modular Software
 * 
 * NeMoS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * NeMoS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with NeMoS.  If not, see <http://www.gnu.org/licenses/>.
 */
package nemos;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Launcher : The NeMoS main launcher.
 * 
 * @author Romain DUBOIS
 */
public class Launcher {

    /**
     * The system property name which is used to specify an alternative launcher
     * class
     */
    private static final String LAUNCHER_CLASS_PROPERTY = "nemos.launch.class"; //$NON-NLS-1$

    /** The default framework main classes */
    private static final String[] FRAMEWORK_MAIN_CLASSES = new String[] { "org.apache.felix.main.Main" }; //$NON-NLS-1$

    /** The main method name */
    private static final String MAIN_METHOD_NAME = "main"; //$NON-NLS-1$

    /**
     * The NeMoS entry point.
     * 
     * @param pArgs
     *            The command-line arguments
     * @throws Throwable
     *             If an error occurred during framework launch
     */
    public static void main(final String[] pArgs) throws Throwable {
        boolean lLaunched = false;

        // Try specified class (if any)
        final String lLauncherClass = System.getProperty(LAUNCHER_CLASS_PROPERTY);
        if (lLauncherClass != null && !lLauncherClass.isEmpty()) {
            lLaunched = launch(lLauncherClass, pArgs);
        }

        // Then the default framework main classes
        for (final String lDefaultClass : FRAMEWORK_MAIN_CLASSES) {
            if (!lLaunched) {
                lLaunched = launch(lDefaultClass, pArgs);
            }
        }

        // No framework found!
        if (!lLaunched) {
            System.err.println("No OSGi framework found"); //$NON-NLS-1$
        }
    }

    /**
     * Try to launch provided main class.
     * 
     * @param pClassName
     *            The main class full name
     * @param pArgs
     *            The launch arguments
     * @return If launch succeeded
     * @throws Throwable
     *             If an error occurred during framework launch
     */
    private static boolean launch(final String pClassName, final String[] pArgs) throws Throwable {
        // Find 'main' method
        final Method lMainMethod;
        try {
            final Class<?> lLauncherClass = Class.forName(pClassName);
            lMainMethod = lLauncherClass.getDeclaredMethod(MAIN_METHOD_NAME, String[].class);
        } catch (final Exception e) {
            // Unable to find that framework
            return false;
        }

        // Call the 'main' method
        try {
            lMainMethod.invoke(null, (Object) pArgs);
        } catch (final InvocationTargetException e) {
            throw e.getCause();
        }

        // Call succeeded
        return true;
    }
}
